#include <time.h>
#include <string.h>

#include "random.h"

int seed_inited = 0;

/* seed 初始化 */
void rand_init()
{
	srand(time(NULL));
	seed_inited = 1;
}

void _make_sure_seed_inited()
{
	if (!seed_inited)
		rand_init();
}

/* 
 * 生成在[lower, upper]范围内的随机数
 * @param lower 下限
 * @param upper 上限
 * @return 随机数
 * @note lower,upper为闭区间
 */
int rand_range(int lower, int upper)
{
	_make_sure_seed_inited();
	double v = rand();
	return (int) (lower + v / RAND_MAX * (upper - lower));
}

/* 
 * 对一段数据随机排序
 * @param base 基地址
 * @param nmemb 数据个数
 * @param size 每个数据大小
 * @return 排序后的数据
 * @note 排序为就地排序 若原始数据之间的顺序有用，应保存原始数据或使用副本调用此接口
 */
void rand_shuffle(void *base, int nmemb, size_t size)
{
	size_t i,  pos;
	void *tmp = malloc(size);

	_make_sure_seed_inited();

#if 0
	/*
	 * 依次选一个数据与首个数据交换
	 */
	for (i=0; i<nmemb-1; i++) {
		pos = rand_range(1,nmemb);
		printf("  [select %d pos] \n", pos);
		memcpy(tmp, base, size);
		memcpy(base, (char *)base + pos*size, size);
		memcpy((char *)base + pos*size, tmp, size);
	}
#else
	/*
	 * 依次为每个位置选择一个数据
	 */
	for (i=0; i<nmemb; i++) {
		pos = rand_range(0, nmemb-1);
		if (pos != i) { // 选择的数据不在位置
			memcpy(tmp, (char *)base + i * size, size);
			memcpy((char *)base + i *size, (char *)base + pos * size, size);
			memcpy((char *)base + pos * size, tmp, size);
		}
	}
	free(tmp);
#endif
}

